package com.yanqu.road.web;

import com.mysql.jdbc.StringUtils;
import com.yanqu.road.AgentServer;
import com.yanqu.road.NettyMgr;
import com.yanqu.road.dao.db.DBManager;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.logic.bussiness.servercenter.ServerBussiness;
import com.yanqu.road.logic.config.ChannelConfig;
import com.yanqu.road.logic.redis.RedisManger;
import com.yanqu.road.reids.subpub.RedisReliableMessageSubPub;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.TempServer;
import com.yanqu.road.server.manger.*;
import com.yanqu.road.server.redis.SystemConfigRedisSubPub;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.ServerType;
import com.yanqu.road.utils.config.Config;
import com.yanqu.road.utils.executor.GeneralThreadFactory;
import com.yanqu.road.utils.net.ServerNetConfigHelper;
import com.yanqu.road.web.listen.GameWebInitListener;
import com.yanqu.road.web.mgr.*;
import com.yanqu.road.web.redis.subpub.impl.CenterManagerReloadSubPub;
import com.yanqu.road.web.redis.subpub.impl.LunTanSignInSubPub;
import com.yanqu.road.web.redis.subpub.impl.ZfbIndexSettingSubPub;
import com.yanqu.road.web.timer.GeneralAgentTimerMgr;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class WebServer extends TempServer {

    private static String configFile = "web.properties";

    private static final Logger logger = LogManager.getLogger(WebServer.class.getName());

    private static WebServer webServer;

    private boolean isUserCenter;

    private boolean needSend = false;

    private static ExecutorService webExecutor;

    private WebServer() {
        String webConfigFile = Config.getWebConfigFile();
        if (StringUtils.isNullOrEmpty(webConfigFile)) {
            return;
        }
        if (webConfigFile.length() > 0) {
            configFile = webConfigFile;
        }
    }

    public static WebServer getInstance() {
        if (webServer == null) {
            webServer = new WebServer();
        }
        return webServer;
    }

    @Override
    public boolean start() {
        lastComponentInitTime = System.currentTimeMillis();
        setServerType(ServerType.SERVER_WEB);
        //获取根目录
        String path = GameWebInitListener.getConfigPath();
        if (!initGameModule(ConfigHelper.initConfig(path + configFile), "load config")) {
            return false;
        }
        System.setProperty("log4j.configurationFile", path + ConfigHelper.getValue("log4j.path"));
        RedisManger.initConfig(path + ConfigHelper.getValue("redis.path"));

        String debug = ConfigHelper.getValue("debug");
        if (null!= debug && Boolean.valueOf(debug)){
            Config.setDebug(true);
        }
        String connectCrossId = ConfigHelper.getValue("connectCrossId");
        if (null != connectCrossId){
            List<Long> crossIds = com.yanqu.road.utils.string.StringUtils.stringToLongList(connectCrossId, ",");
            Config.setConnectCrossId(crossIds);
        }


        try {//加载数据库驱动程序
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            logger.error("load mysql db driver error", e);
            return false;
        }

        isUserCenter = "1".equals(ConfigHelper.getValue("isUserCenter"));
        needSend = "1".equals(ConfigHelper.getValue("needSend"));
        webExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new GeneralThreadFactory("webThread"));
        if (!isUserCenter) {
            cfgPath = path + configFile;
            GameServer.gameStart(path + configFile);
            AgentServer.agentStart(path + configFile);
        }else {//中心服务器

            String versionInfo = "v4.0.0_release";
            Properties properties = readGitProperties();
            if (properties != null) {
                String property = properties.getProperty("git.branch");
                if (property != null) {
                    versionInfo = properties.getProperty("git.branch");
                }
            }
            logger.info("backend code version . " + versionInfo);
            System.err.println("backend code version . " + versionInfo);

            if (!initGameModule(DBManager.initConfig(path + ConfigHelper.getValue("db.path")), "load db")) {
                return false;
            }
        }

        if (!initGameModule(DBManager.initGameDbConfig(ServerType.SERVER_WEB), "load game db")) {
            return false;
        }

        if (!initGameModule(ServerNetConfigHelper.init(DBManager.getNetConfigFromDb()), "load net")) {
            return false;
        }

        refreshGameConfig();

        sid = Integer.parseInt(ConfigHelper.getValue("serverId"));
        int channelId = 0;
        ServerInfo serverInfo = ServerBussiness.getServerInfoByServerId(sid);
        if (null != serverInfo) {
            channelId = serverInfo.getChannelId();
        }
        ChannelConfig.reloadChannelConfig(channelId);

        if (!initGameModule(initTempMgrList(), "init all mgr list")) {
            return false;
        }
        RedisReliableMessageSubPub.addSubPub(new LunTanSignInSubPub());
        RedisReliableMessageSubPub.addSubPub(new SystemConfigRedisSubPub());
        RedisReliableMessageSubPub.addSubPub(new ZfbIndexSettingSubPub());
        if(!isUserCenter) {
            if(Config.isDebug()){
                RedisReliableMessageSubPub.addSubPub(new CenterManagerReloadSubPub());
            }
            RedisReliableMessageSubPub.getInstance().subscribe();
        }else {
            //登录、充值都注册，先简单做
            RedisReliableMessageSubPub.getList().clear();
            RedisReliableMessageSubPub.addSubPub(new CenterManagerReloadSubPub());
            RedisReliableMessageSubPub.getInstance().subscribe();
            RedisReliableMessageSubPub.addSubPub(new LunTanSignInSubPub());
            RedisReliableMessageSubPub.addSubPub(new SystemConfigRedisSubPub());
            RedisReliableMessageSubPub.addSubPub(new ZfbIndexSettingSubPub());
        }

        logger.info("current path:{}", path);
        logger.info("GameWeb start success");
        logger.info("notify process start success!");  //日志启动成功标识

        for (int i = 0; i < 100; i++) {
            logger.info("--------------");
        }
        logger.info("notify process start success!");  //日志启动成功标识

        TempServer.tempServerLogger.info("notify process start success!");


        //注册异常关闭处理过程
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            if(isUserCenter){
                logger.info("WebServer kill 关闭服务器");
                WebServer.getInstance().newStop();
                tempServerLogger.info("notify process stop success!");
            }else {
                logger.info("WebServer kill 关闭服务器");
                boolean agentStop = AgentServer.getInstance().newStop();
                boolean gameStop = GameServer.getInstance().newStop();
                boolean webStop = WebServer.getInstance().newStop();
                logger.info("------------");
                logger.info("------------");
                logger.info("------------");
                logger.info("------------");
                NettyMgr.stop();
                logger.info("agentStop: {}, gameStop: {}, webStop: {}", agentStop, gameStop, webStop);
                if (agentStop && gameStop && webStop) {
                    logger.info("notify process stop success!");
                    tempServerLogger.info("notify process stop success!");
                    Runtime.getRuntime().halt(1);
                }
            }
        }));

        return true;
    }

    public boolean newStop() {
        try {
            logger.info("------------");
            logger.info("------------");
            logger.info("------------");
            logger.info("------------");
            TempServer.deleteFile("./gameWeb.pid");
         //   super.stopWithLogger();

            // 埋点关闭
            // new WebDataAnalyticsMgr().stop();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {

        }

        return true;
    }

    @Override
    public List<TempMgr> getMgrList() {
        List<TempMgr> mgrList = new ArrayList<>();
        //没事别改顺序，不清楚的记得问
        mgrList.add(new ConfigManageMgr());
        mgrList.add(new ConfigMgr());
        mgrList.add(new ForbiddenMgr());
        mgrList.add(new ChannelVersionMgr());
        mgrList.add(new PackageVersionMgr());
        mgrList.add(new HotPackVersionMgr());
        mgrList.add(new ChannelHotUpdateConfigMgr());
        mgrList.add(new ServerListMgr());
        mgrList.add(new AppKeyMgr());
        mgrList.add(new ChannelConfigMgr(sType));
        mgrList.add(new ServerConfigMgr());
        mgrList.add(new H5AppletUrlMgr());
        mgrList.add(new MallMgr());
        mgrList.add(new ChannelNoticeMgr());
        mgrList.add(new ChannelTabNoticeMgr());
        if(!isUserCenter) {
            mgrList.add(new UserIdMgr());
        }else {
            mgrList.add(new AdminMgr());
        }
        mgrList.add(new InnerUserMgr());
        mgrList.add(new WebServiceMgr());
        mgrList.add(new GeneralAgentTimerMgr());
        mgrList.add(new LogMgr());
        mgrList.add(new WhiteIpMgr());
        mgrList.add(new PlatformUserIdMgr());
        mgrList.add(new LoginPlayerQueueMgr());
//        mgrList.add(new ForbiddenWordMgr());
        mgrList.add(new MultipleLanguageMgr());
        mgrList.add(new NameMgr());
        mgrList.add(new DecorationMgr());
        mgrList.add(new ActivityMallMgr());
        mgrList.add(new RegisterPlayerNumMgr());
        mgrList.add(new AppIdPlatformPolicyMgr());
        mgrList.add(new RoleCreateCountMgr());
        mgrList.add(new PlatformPolicyMgr());
        mgrList.add(new TokenOrderWhiteMgr());
        mgrList.add(new AnnualReportMgr());
        mgrList.add(new AllActivityMainInfoMgr());

        //3合1 不需要重复
        //mgrList.add(new DAServerListMgr());
        //mgrList.add(new WebDataAnalyticsMgr());
        mgrList.add(new CnActivityMgr());
        mgrList.add(new SqlCacheMgr());
        mgrList.add(new ForbiddenWordOverSeasMgr());
        mgrList.add(new AutoOpenServerMgr());
		return mgrList;
	}

    public boolean isUserCenter() {
        return isUserCenter;
    }

    public boolean isNeedSend() {
        return needSend;
    }

    public static ExecutorService getWebExecutor() {
        return webExecutor;
    }

    public static void setWebExecutor(ExecutorService webExecutor) {
        WebServer.webExecutor = webExecutor;
    }

    private Properties readGitProperties() {
        InputStream inputStream = null;
        try {
            ClassLoader classLoader = getClass().getClassLoader();
            inputStream = classLoader.getResourceAsStream("git.properties");
            Properties gitProperties = new Properties();
            gitProperties.load(inputStream);
            return gitProperties;
        } catch (Exception e) {
            logger.error("get git version info fail", e);
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (Exception e) {
                logger.error("close inputStream fail", e);
            }
        }
        return null;
    }
}
